package com.fangcai.es.practise2_qq_user_search.service;

import com.alibaba.fastjson.JSONObject;
import com.fangcai.es.common.exception.EsDemoException;
import com.fangcai.es.common.response.PageResponse;
import com.fangcai.es.common.util.CommonUtil;
import com.fangcai.es.practise2_qq_user_search.entity.QqUser;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @author MouFangCai
 * @date 2020/10/13 15:48
 * @description
 */
@Service
public class QqUserServiceImpl {

    private final static String QUERY_FIELD = "nickName.pinyin";
    private final static String ES_INDEX_NAME = "user_index_v2";

    @Autowired
    private RestHighLevelClient esClient;



    public PageResponse<QqUser> listByStr (String queryStr, Integer pageNum, Integer pageSize) {
        PageResponse<QqUser> pageResponse = new PageResponse<>();
        pageResponse.setPageNum(pageNum);
        pageResponse.setPageSize(pageSize);

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        // 保证检索结果必须包含中文字
        String chineseStr = CommonUtil.getChineseStr(queryStr);
        if (StringUtils.isNotEmpty(chineseStr)) {
            boolQuery.filter(QueryBuilders.matchQuery(QUERY_FIELD, chineseStr)
                    .analyzer("standard").minimumShouldMatch("100%"));
        }
        // 中文 + 全拼 + 首字母 混合检索
        boolQuery.must(QueryBuilders.matchPhrasePrefixQuery(QUERY_FIELD,queryStr));
        // 高亮设置
        HighlightBuilder highlighter = new HighlightBuilder();
        highlighter.field(QUERY_FIELD).preTags("<span class=\"search-highlight\">").postTags("</span>");
        // 使用该选项根本不会分割文本，高亮显示字段的全部内容
        highlighter.numOfFragments(0);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.size(pageSize).from(pageSize * (pageNum - 1));
        searchSourceBuilder.query(boolQuery);
        searchSourceBuilder.highlighter(highlighter);

        /**
         * 对于高亮显示的检索，后面再统一封装为utils
         */
        SearchRequest searchRequest = new SearchRequest(ES_INDEX_NAME);
        searchRequest.source(searchSourceBuilder);
        try {
            SearchResponse response = esClient.search(searchRequest, RequestOptions.DEFAULT);
            pageResponse.setTotal(response.getHits().getTotalHits().value);
            List<QqUser> dataList = new ArrayList<>();
            SearchHits hits = response.getHits();

            for(SearchHit hit : hits){
                QqUser qqUser = JSONObject.parseObject(hit.getSourceAsString(), QqUser.class);
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                HighlightField nameHighLight = highlightFields.get(QUERY_FIELD);
                if (nameHighLight != null) {
                    qqUser.setNickName(Arrays.toString(nameHighLight.getFragments()));
                }
                dataList.add(qqUser);
            }
            pageResponse.setData(dataList);
        } catch (Exception e) {
            e.printStackTrace();
            throw new EsDemoException(String.valueOf(HttpStatus.BAD_REQUEST),
                    "error to execute searching,because of " + e.getMessage());
        }
        return pageResponse;
    }


}
